package org.zoomdev.zoom.web.test;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.zoomdev.zoom.common.utils.Classes;
import org.zoomdev.zoom.ioc.Ioc;
import org.zoomdev.zoom.ioc.impl.builder.IocBuilder;
import org.zoomdev.zoom.server.modules.SystemWebServerModule;

import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("deprecation")
public class MvcTestRunner extends BlockJUnit4ClassRunner {

    private final Class<?> clazz;

    private final Ioc ioc;


    public MvcTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
        this.clazz = klass;

        Map<String, String> param = new HashMap<>();
        ModuleFilter moduleFilter = clazz.getAnnotation(ModuleFilter.class);
        if (moduleFilter != null) {
            param.put("zoom.scan.modules", moduleFilter.value());
        }

        ScanFilter scanFilter = clazz.getAnnotation(ScanFilter.class);
        if (scanFilter != null) {
            param.put("zoom.scan.filter", scanFilter.value());
        }


        ControllerFilter controllerFilter = clazz.getAnnotation(ControllerFilter.class);
        if (controllerFilter != null) {
            param.put("zoom.scan.controllers", controllerFilter.value());
        }


        IocBuilder builder = new IocBuilder();
        builder.setExceptModules(SystemWebServerModule.class);
        builder.createParameters(param);
        this.ioc = builder.build();

    }

    // 拦截 BeforeClass 事件
//    protected Statement withBeforeClasses(final Statement statement) {
//        final Statement junitStatement = super.withBeforeClasses(statement);
//        return new Statement() {
//            @Override
//            public void evaluate() throws Throwable {
//                System.out.println("Before Class: " + clazz.getName());
//                junitStatement.evaluate();
//            }
//
//        };
//    }

    // 拦截每一个方法的 Before 事件
    protected Statement withBefores(final FrameworkMethod method, Object target, final Statement statement) {

        ioc.inject(target);

        final Statement junitStatement = super.withBefores(method, target, statement);
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                // System.out.println("Before before method: " + method.getName() + ":" + target);
                junitStatement.evaluate();
                //System.out.println("After before method: " + method.getName());
            }
        };
    }

//    // 截获每一个测试方法的 after 事件
//    protected Statement withAfters(final FrameworkMethod method, Object target, final Statement statement) {
//        final Statement junitStatement = super.withAfters(method, target, statement);
//        return new Statement() {
//            @Override
//            public void evaluate() throws Throwable {
//                System.out.println("After method: " + method.getName());
//                junitStatement.evaluate();
//            }
//
//        };
//    }

    // 截获测试类的 after 事件
    protected Statement withAfterClasses(final Statement statement) {
        final Statement junitStatement = super.withAfterClasses(statement);
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                junitStatement.evaluate();
                Classes.destroy(ioc);
                //System.out.println("After Class: " + clazz.getName());
            }
        };
    }
}